#include "Acceptor.h"
#include "Logger.h"
#include "InetAddress.h"

#include <sys/types.h>
#include <sys/socket.h>
#include <cerrno>
#include <unistd.h>

static int createNonblocking()
{
    int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    if (sockfd < 0)
    {
        LOG_FATAL("%s:%d:listensocket creat error: %d: %s",
                  __FILE__, __LINE__, errno, strerror(errno));
    }
    return sockfd;
}

Acceptor::Acceptor(EventLoop *loop, const InetAddress &listenAddr, bool reuseport)
    : loop_(loop)
    , acceptSocket_(createNonblocking()) // 1.创建listen套接字
    , acceptChannel_(loop, acceptSocket_.fd()) // 打包listen套接字的cahnnel
    , listenning_(false)
{
    acceptSocket_.setReuseAddr(true);
    // acceptSocket_.setReusePort(reuseport);
    acceptSocket_.setReusePort(true);
    acceptSocket_.bindAddress(listenAddr); // 2.绑定本地ip port

    acceptChannel_.setReadCallback(std::bind(&Acceptor::handleRead, this)); // 注册listen套接字的读事件函数
}
Acceptor::~Acceptor()
{
    acceptChannel_.disableAll(); // 取消poller的托管
    acceptChannel_.remove();     // 从poller的channels中移除
}

void Acceptor::listen()
{
    listenning_ = true;
    acceptSocket_.listen();         // 3.监听
    acceptChannel_.enableReading(); // 将acceptChannel托管给poller，并设置关心读事件
}

// listen套接字的读事件处理函数
void Acceptor::handleRead()
{
    // 到此listen套接字的读事件发生，说明有连接请求
    InetAddress peerAddr;
    int connfd = acceptSocket_.accept(&peerAddr); // 4.接收新连接
    if (connfd >= 0)
    {
        if (newConnectionCallback_)
        {
            newConnectionCallback_(connfd, peerAddr); // 轮询，找到subloop，唤醒，分发新连接的channel
        }
        else
        {
            close(connfd);
        }
    }
    else
    {
        LOG_ERROR("%s:%d:error: %d: %s", __FILE__, __LINE__, errno, strerror(errno));
    }
}